from decimal import Decimal

from sqlalchemy import func
from sqlalchemy.orm import Session

from module_admin.entity.do.cms_driver import CmsDriver
from module_admin.entity.do.cms_order_execute import CmsOrderExecute
from module_admin.entity.vo.cms_car_vo import OrderListMessage, OrderListMessageForQuery
from module_admin.entity.vo.cms_home_vo import MyTime
from module_admin.entity.vo.cms_order_bill_vo import OrderBillModelForUpdate
from module_admin.entity.vo.cms_order_execute_vo import OrderExecuteModel
from utils.time_format_util import object_format_datetime, list_format_datetime


class CmsOrderExecuteDao:

    @classmethod
    def create_order_execute(cls, db: Session, page_object: OrderExecuteModel):
        object_dict = page_object.dict()
        if "expenses" in object_dict:
            del object_dict["expenses"]
        if "sheet_expenses" in object_dict:
            del object_dict["sheet_expenses"]
        cms_order_execute = CmsOrderExecute(**object_dict)
        db.add(cms_order_execute)
        db.flush()
        db.commit()

    @classmethod
    def update_order_execute_by_id(cls, db: Session, order_bill_update_dict: dict):
        db.query(CmsOrderExecute) \
            .filter(CmsOrderExecute.id == order_bill_update_dict.get('id')) \
            .update(order_bill_update_dict)
        db.commit()

    @classmethod
    def update_execute_bill_by_order_id(cls, db, order_update: OrderBillModelForUpdate, order_id: str):
        order_execute: CmsOrderExecute = CmsOrderExecuteDao.get_one_by_order_id(db, order_id)
        if order_update.sheet_mileage is not None:
            order_execute.sheet_mileage = order_update.sheet_mileage
        db.commit()

    @classmethod
    def get_one_by_order_id(cls, db: Session, order_id: str):
        first = db.query(CmsOrderExecute).filter(CmsOrderExecute.order_id == order_id).first()
        return object_format_datetime(first)

    @classmethod
    def get_one_by_order_id_and_driver_id(cls, db: Session, order_id: str, driver_id: str):
        first = (db.query(CmsOrderExecute)
                 .filter(CmsOrderExecute.order_id == order_id)
                 .filter(CmsOrderExecute.driver_id == driver_id)
                 .first())
        return object_format_datetime(first)

    @classmethod
    def get_order_id_list_by_car_id(cls, db: Session, car_id: int):
        order_id_list = db.query(CmsOrderExecute.order_id) \
            .filter(CmsOrderExecute.car_id == str(car_id)) \
            .filter(CmsOrderExecute.end_mileage is None) \
            .all()
        order_id_list2 = {int(id[0]) for id in order_id_list}
        return order_id_list2

    @classmethod
    def get_order_id_list_by_driver_id(cls, db: Session, driver_id: int):
        order_id_list = db.query(CmsOrderExecute.order_id) \
            .filter(CmsOrderExecute.driver_id == str(driver_id)) \
            .filter(CmsOrderExecute.end_mileage is None) \
            .all()
        order_id_list2 = {int(id[0]) for id in order_id_list}
        return order_id_list2

    @classmethod
    def get_sum_mileage_by_time(cls, db: Session, time: MyTime):
        mileage = db.query(func.sum(CmsOrderExecute.sheet_mileage)) \
            .filter(CmsOrderExecute.reality_end_time >= time.start_time.strftime('%Y-%m-%d %H:%M:%S')) \
            .filter(CmsOrderExecute.reality_end_time < time.end_time.strftime('%Y-%m-%d %H:%M:%S')) \
            .scalar()
        return mileage if mileage is not None else Decimal(0)

    @classmethod
    def get_sum_order_start_by_time(cls, db: Session, time: MyTime):
        mileage = db.query(func.count(CmsOrderExecute.id)) \
            .filter(CmsOrderExecute.create_time >= time.start_time.strftime('%Y-%m-%d %H:%M:%S')) \
            .filter(CmsOrderExecute.create_time < time.end_time.strftime('%Y-%m-%d %H:%M:%S')) \
            .scalar()
        return mileage if mileage is not None else 0
